/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "I2c.h"
#include "Sdrv_I2c.h"
#include "I2c_Cfg.h"
#include "SchM_I2c.h"
#if (I2C_DEV_ERROR_DETECT == STD_ON)
#include "Det.h"
#endif /* (I2C_DEV_ERROR_DETECT == STD_ON) */

#define I2C_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

I2c_msg_t I2c_msgs[I2C_CHN_NUM][SDRV_I2C_MSG_NUM_MAX] LOCATE_ALIGNED(I2C_CACHE_LINE);

#define I2C_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"

/********************************************************************************************************
 *                                  Private Variable Definitions                                        *
 *******************************************************************************************************/
#if (STD_ON == I2C_CORE0_ENABLE)
#define I2C_CORE0_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
/** Save the configuration and channel status information of core0. */
static sdrv_I2c_dev_t I2c_HandlerCore0[I2C_CHN_NUM] LOCATE_ALIGNED(I2C_CACHE_LINE);
#define I2C_CORE0_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
#endif /** #if (STD_ON == I2C_CORE0_ENABLE) */

#if (STD_ON == I2C_CORE1_ENABLE)
#define I2C_CORE1_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
/** Save the configuration and channel status information of core1. */
static sdrv_I2c_dev_t I2c_HandlerCore1[I2C_CHN_NUM] LOCATE_ALIGNED(I2C_CACHE_LINE);
#define I2C_CORE1_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
#endif /** #if (STD_ON == I2C_CORE1_ENABLE) */

#if (STD_ON == I2C_CORE2_ENABLE)
#define I2C_CORE2_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
/** Save the configuration and channel status information of core2. */
static sdrv_I2c_dev_t I2c_HandlerCore2[I2C_CHN_NUM] LOCATE_ALIGNED(I2C_CACHE_LINE);
#define I2C_CORE2_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
#endif /** #if (STD_ON == I2C_CORE2_ENABLE) */

#if (STD_ON == I2C_CORE3_ENABLE)
#define I2C_CORE3_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
/** Save the configuration and channel status information of core3. */
static sdrv_I2c_dev_t I2c_HandlerCore3[I2C_CHN_NUM] LOCATE_ALIGNED(I2C_CACHE_LINE);
#define I2C_CORE3_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "I2c_MemMap.h"
#endif /** #if (STD_ON == I2C_CORE3_ENABLE) */


#define I2C_START_SEC_CONST_UNSPECIFIED
#include "I2c_MemMap.h"

/********************************************************************************************************
 *                                  Private Constant Definitions                                        *
 *******************************************************************************************************/
/**  I2c Handler */
sdrv_I2c_dev_t *const I2c_Handler[CPU_MAX_CORE_NUMBER] =
{
#if (STD_ON == I2C_CORE0_ENABLE)
    &I2c_HandlerCore0[0],
#else
    NULL_PTR,
#endif /** #if (STD_ON == I2C_CORE0_ENABLE) */
#if (STD_ON == I2C_CORE1_ENABLE)
    &I2c_HandlerCore1[0],
#else
    NULL_PTR,
#endif /** #if (STD_ON == I2C_CORE1_ENABLE) */
#if (STD_ON == I2C_CORE2_ENABLE)
    &I2c_HandlerCore2[0],
#else
    NULL_PTR,
#endif /** #if (STD_ON == I2C_CORE2_ENABLE) */
#if (STD_ON == I2C_CORE3_ENABLE)
    &I2c_HandlerCore3[0],
#else
    NULL_PTR,
#endif /** #if (STD_ON == I2C_CORE3_ENABLE) */
};

#define I2C_STOP_SEC_CONST_UNSPECIFIED
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE
#include "I2c_MemMap.h"

/**
 * @brief Forces the I2C adapter to a specific transaction state.
 *
 * This function sets the transaction state of the I2C adapter to the specified state.
 * It checks if the adapter pointer is NULL and reports an error if it is.
 * The function also checks if the specified state is valid and only sets the state if it is.
 *
 * @param channelId The channel ID of the I2C configuration.
 * @param setTranstate The desired transaction state.
 *
 * @return 0 if the state was set successfully, -1 if the adapter pointer is NULL.
 */
Std_ReturnType I2c_ForceTranstate(uint8 channelId, uint32 setTranstate)
{
    Std_ReturnType errorId = E_OK;
    uint32 coreId = I2c_GetCoreId();
    I2c_adap_dev_t *adap;

    adap = &I2c_Handler[coreId][channelId].adap;

    if ((channelId >= I2C_CHN_NUM) || NULL_PTR == I2c_Handler[coreId]
            || setTranstate > (uint32)I2C_NACK_STATE)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSTATE_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else
    {
        adap->trans_state = (I2c_trans_state_t)setTranstate;
    }

    return errorId;
}

/**
 * @brief Gets the current I2C adapter initialization state.
 *
 * This function takes a pointer to an I2c_adap_dev_t structure as input and returns the current initialization state of the I2C adapter.
 *
 * @param channelId The channel ID of the I2C configuration.
 *
 * @return The current initialization state of the I2C adapter, or I2C_UNDEFINEINIT_STATE if the input pointer is NULL.
 */
I2c_init_state_t I2c_GetInitState(uint8 channelId)
{
    uint32 coreId = I2c_GetCoreId();
    I2c_adap_dev_t *adap;
    I2c_init_state_t initState;

    adap = &I2c_Handler[coreId][channelId].adap;

    if ((channelId >= I2C_CHN_NUM) || NULL_PTR == I2c_Handler[coreId])
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_INITSTATE_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        initState = I2C_UNDEFINEINIT_STATE;
    }
    else
    {
        initState = adap->status;
    }

    return initState;
}
#define I2C_STOP_SEC_CODE
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE_FAST
#include "I2c_MemMap.h"
/**
 * @brief Gets the current I2C adapter state.
 *
 * This function takes a pointer to an I2c_adap_dev_t structure as input and returns the current state of the I2C adapter.
 *
 * @param channelId The channel ID of the I2C configuration.
 *
 * @return I2c_trans_state_t The current state of the I2C adapter.
 */
I2c_trans_state_t I2c_GetTranState(uint8 channelId)
{
    uint32 coreId = I2c_GetCoreId();
    I2c_adap_dev_t *adap;
    I2c_trans_state_t tansState;

    adap = &I2c_Handler[coreId][channelId].adap;

    if ((channelId >= I2C_CHN_NUM) || NULL_PTR == I2c_Handler[coreId])
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSTATE_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        tansState = I2C_UNDEFINETRANS_STATE;
    }
    else
    {
        tansState = adap->trans_state;
    }

    return tansState;
}

/**
 * @brief Performs an I2C transfer operation.
 *
 * This function takes a pointer to an I2c_adap_dev_t structure, a pointer to an array of I2c_msg structures, and the number of messages to transfer.
 *
 * It checks for invalid parameters and adapter status, and then performs the transfer operation using the provided messages.
 *
 * @param channelId The channel ID of the I2C configuration.
 * @param msgs A pointer to an array of I2c_msg structures.
 * @param num The number of messages to transfer.
 *
 * @return The result of the transfer operation. A value of 0 indicates success, while a negative value indicates failure.
 */
Std_ReturnType I2c_Transfer(uint8 channelId, struct I2c_msg *msgs, uint8 num)
{
    Std_ReturnType errorId = E_OK;
    boolean busyFlag = FALSE;
    uint32 coreId = I2c_GetCoreId();
    I2c_adap_dev_t *adap;

    adap = &I2c_Handler[coreId][channelId].adap;

    if ((channelId >= I2C_CHN_NUM) || (NULL_PTR == I2c_Handler[coreId]) || (NULL_PTR == msgs)
            || (num < 1U) || (num > SDRV_I2C_MSG_NUM_MAX))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSFER_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else if (adap->status != I2C_INIT_STATE)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSFER_ID,
                              (uint8)I2C_E_UNINIT);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_UNINIT;
    }
    /* I2C_USPEED can not read */
    else if ((I2C_USPEED == adap->speed) && ((msgs[0].rw_flag & I2C_M_R)
             || (msgs[num - 1].rw_flag & I2C_M_R)))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_TRANSFER_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else
    {
        /* check and update adap owner statue */
        SchM_Enter_I2c_I2C_EXCLUSIVE_AREA_00();

        if (adap->adap_State == I2C_ADAP_IDLE)
        {
            adap->adap_State = I2C_ADAP_BUSY;
            busyFlag = TRUE;
        }

        SchM_Exit_I2c_I2C_EXCLUSIVE_AREA_00();

        if (TRUE == busyFlag)
        {
            if (adap->trans_state != I2C_BUSY_STATE)
            {
                errorId = sdrv_I2c_xfer(adap, msgs, num);
            }
            else
            {
                errorId = I2C_E_TRANSMIT_EXCEPTION;
            }

            /* update adap owner statue */
            SchM_Enter_I2c_I2C_EXCLUSIVE_AREA_00();
            adap->adap_State = I2C_ADAP_IDLE;
            SchM_Exit_I2c_I2C_EXCLUSIVE_AREA_00();
        }
        else
        {
            errorId = I2C_E_TRANSMIT_EXCEPTION;
        }
    }

    return errorId;
}

/**
 * @brief Writes data to an I2C device.
 *
 * This function performs a write operation on an I2C bus. It takes a pointer to an I2c_adap_dev_t structure,
 * the address of the I2C device, a pointer to the write buffer, and the length of the write buffer.
 *
 * @param channelId The channel ID of the I2C configuration.
 * @param addr The address of the I2C device.
 * @param wbuf A pointer to the write buffer.
 * @param wlen The length of the write buffer.
 *
 * @return The status of the operation. A value of 0 indicates success, while a negative value indicates failure.
 */
Std_ReturnType I2c_Write(uint8 channelId, uint16 addr,
                         uint8 *wbuf, uint16 wlen)
{
    Std_ReturnType errorId = E_OK;
    I2c_msg_t msgs[1];

    if ((channelId >= I2C_CHN_NUM) || (NULL_PTR == wbuf) || (wlen < 1U))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_WRITE_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else
    {
        msgs[0].addr = addr;
        msgs[0].buf = wbuf;
        msgs[0].len = wlen;
        msgs[0].rw_flag = (uint32)I2C_M_W;
        errorId = I2c_Transfer(channelId, msgs, 1U);
    }

    return errorId;
}

/**
 * @brief Performs a read operation on an I2C bus.
 *
 * This function reads data from an I2C device at the specified address and stores it in the provided buffer.
 *
 * @param channelId The channel ID of the I2C configuration.
 * @param addr  The address of the I2C device to read from.
 * @param rbuf A pointer to the buffer to store the read data.
 * @param rlen  The length of the data to read.
 *
 * @return  The status of the operation. A value of 0 indicates success, while a negative value indicates failure.
 */
Std_ReturnType I2c_Read(uint8 channelId, uint16 addr,
                        uint8 *rbuf, uint16 rlen)
{
    Std_ReturnType errorId = E_OK;
    I2c_msg_t msgs[1];

    if ((channelId >= I2C_CHN_NUM) || (NULL_PTR == rbuf) || (rlen < 1U))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_READ_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else
    {
        msgs[0].addr = addr;
        msgs[0].buf = rbuf;
        msgs[0].len = rlen;
        msgs[0].rw_flag = (uint32)I2C_M_R;
        errorId = I2c_Transfer(channelId, msgs, 1U);
    }

    return errorId;
}

/**
 * @brief  This function performs a combined write-read operation on an I2C bus.
 *
 * @param channelId The channel ID of the I2C configuration.
 * @param  addr  The slave address to be accessed.
 * @param  wbuf  Pointer to the write buffer.
 * @param  wlen  The length of the write buffer.
 * @param  rbuf  Pointer to the read buffer.
 * @param  rlen  The length of the read buffer.
 *
 * @return  The status of the operation. A value of 0 indicates success, while a negative value indicates failure.
 */
Std_ReturnType I2c_WriteRead(uint8 channelId, uint16 addr,
                             uint8 *wbuf, uint16 wlen,  uint8 *rbuf, uint16 rlen)
{
    Std_ReturnType errorId = E_OK;
    I2c_msg_t msgs[2];

    if ((channelId >= I2C_CHN_NUM) || (NULL_PTR == wbuf) || (NULL_PTR == rbuf) || (rlen < 1U)
            || (wlen < 1U))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_WRITE_READ_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else
    {
        msgs[0].addr = addr;
        msgs[0].buf = wbuf;
        msgs[0].len = wlen;
        msgs[0].rw_flag = (uint32)I2C_M_W;

        msgs[1].addr = addr;
        msgs[1].buf = rbuf;
        msgs[1].len = rlen;
        msgs[1].rw_flag = (uint32)I2C_M_R;
        errorId = I2c_Transfer(channelId, msgs, 2U);
    }

    return errorId;
}


/**
 * Initializes the I2C adapter.
 *
 * @param[in,out] adap  Pointer to the I2C adapter device structure.
 *
 * @retval  0  I2C adapter initialized successfully.
 * @retval -1  I2C adapter initialization failed.
 */
Std_ReturnType I2c_SetHighSpeedMode(uint8 channelId, I2c_speed_t speed, uint8 mastercode)
{
    Std_ReturnType errorId = E_OK;
    I2c_adap_dev_t *adap;
    uint32 coreId = I2c_GetCoreId();
    adap = &I2c_Handler[coreId][channelId].adap;

    if ((channelId >= I2C_CHN_NUM) || (NULL_PTR == I2c_Handler[coreId]))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID,
                              (uint8)I2C_SET_HIGHSPEED_MODE_ID, (uint8)I2C_E_NOT_ENABLE);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_NOT_ENABLE;
    }
    else if (adap->status != I2C_INIT_STATE)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID,
                              (uint8)I2C_SET_HIGHSPEED_MODE_ID, (uint8)I2C_E_UNINIT);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_UNINIT;
    }
    else if (adap->speed != I2C_HSPEED || (speed != I2C_HSPEED && speed != I2C_FSPEED))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID,
                              (uint8)I2C_SET_HIGHSPEED_MODE_ID, (uint8)I2C_E_NOT_ENABLE);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }

    else
    {
        if (speed == I2C_HSPEED)
        {
            sdrv_i2c_lld_set_speed(adap->base,
                                   ((SDRV_I2C_HSPEED & I2C_PCR0_SPEED_MASK) << I2C_PCR0_SPEED_BIT)); // Set high-speed mode
            sdrv_i2c_lld_set_mastercode(adap->base, mastercode);
        }
        else
        {
            sdrv_i2c_lld_set_speed(adap->base,
                                   ((SDRV_I2C_NSPEED & I2C_PCR0_SPEED_MASK) << I2C_PCR0_SPEED_BIT)); // Set normal-speed mode
        }
    }

    return errorId;
}

#define I2C_STOP_SEC_CODE_FAST
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE
#include "I2c_MemMap.h"
/**
 * @brief Initializes the I2C module.
 *
 * This function initializes the I2C module by iterating over all I2C channels,
 * configuring the message structure for each channel, and probing the I2C adapter.
 *
 * @return 0 if the initialization is successful, -1 otherwise.
 */
Std_ReturnType I2c_Init(const I2c_adap_cfg_t *ConfigPtr)
{
    Std_ReturnType errorId = E_OK;
    const I2c_adap_cfg_t *cfgConvert;
    I2c_adap_dev_t *adap;
    sdrv_I2c_mdev_t *mdev;
    uint32 coreId = I2c_GetCoreId();
    uint8 channelId;
    uint8 msgid;

    if ((NULL_PTR == I2c_Handler[coreId]) || NULL_PTR == ConfigPtr)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_INIT_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_PARAM_INVALID;
    }
    else
    {
        /* PRQA S 2877  1 */
        for (channelId = 0; channelId < I2C_CHN_NUM; channelId++)
        {
            cfgConvert = &ConfigPtr[channelId];
            mdev = &I2c_Handler[coreId][channelId].mdev;

            if((I2C_INIT_STATE == I2c_Handler[coreId][channelId].adap.status))
            {
                errorId = I2C_E_INIT_FAILURE;
                break;
            }
            else if ((cfgConvert->i2cCoreId == coreId) && (cfgConvert->enable == I2C_EN))
            {
                mdev->msgs = I2c_msgs[channelId];

                for (msgid = 0; msgid < SDRV_I2C_MSG_NUM_MAX; msgid++)
                {
                    mdev->msgs[msgid].addr_flag = cfgConvert->addr_flag;
                    mdev->msgs[msgid].polling = cfgConvert->polling;
                }

                adap = sdrv_I2c_adap_probe(I2c_Handler[coreId], channelId, cfgConvert, cfgConvert->hwCh);
                adap->status = sdrv_I2c_init(adap);

                if ((adap->status) != I2C_INIT_STATE)
                {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
                    (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_ADAP_INIT_ID,
                                        (uint8)I2C_E_INIT_FAILURE);
#endif /* I2C_DEV_ERROR_DETECT */
                    errorId = I2C_E_INIT_FAILURE;
                    break;
                }
            }
            else
            {
                adap = &I2c_Handler[coreId][channelId].adap;
                adap->status = I2C_UNINIT_STATE;
            }
        }
    }

    return errorId;
}

/**
 * @brief Deinitialize the I2C module.
 *
 * This function deinitialize the I2C module by iterating over all I2C channels,
 * configuring the message structure for each channel, and probing the I2C adapter.
 *
 * @return 0 if the deinitialize is successful, -1 otherwise.
 */
Std_ReturnType I2c_Deinit(void)
{
    Std_ReturnType errorId = E_OK;
    uint32 coreId = I2c_GetCoreId();
    I2c_adap_dev_t *adap;
    uint8 channelId;

    if (I2c_Handler[coreId] == NULL_PTR)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_DEINIT_ID,
                              (uint8)I2C_E_NOT_ENABLE);
#endif /* I2C_DEV_ERROR_DETECT */
        errorId = I2C_E_NOT_ENABLE;
    }
    else
    {
        /* PRQA S 2877  1 */
        for (channelId = 0; channelId < I2C_CHN_NUM; channelId++)
        {
            adap = &I2c_Handler[coreId][channelId].adap;

            if (adap->status == I2C_INIT_STATE)
            {
                errorId = sdrv_I2c_deinit(adap);
                if (errorId != E_OK)
                    break;
                adap->status = I2C_UNINIT_STATE;
            }
        }
    }

    return errorId;
}

/**
 * @brief Recovers the I2C adapter state.
 *
 * This function attempts to recover the I2C adapter by checking its current state
 * and invoking the appropriate recovery operations. It handles error detection
 * and ensures that the adapter is not busy before proceeding with the recovery.
 *
 * @param channelId Channel ID in I2C configuration.
 * @return I2C_recov_state_t The state of the recovery process, which can be
 *         either I2C_CLRERR_STATE or I2C_CLRPASS_STATE.
 */
I2c_recov_state_t I2c_Recover(uint8 channelId)
{
    I2c_recov_state_t recovState;
    boolean busyFlag = FALSE;
    uint32 coreId = I2c_GetCoreId();
    I2c_adap_dev_t *adap;
    int ret = -1;

    adap = &I2c_Handler[coreId][channelId].adap;

    if ((channelId >= I2C_CHN_NUM) || (NULL_PTR == I2c_Handler[coreId]))
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_RECOVER_ID,
                              (uint8)I2C_E_PARAM_INVALID);
#endif /* I2C_DEV_ERROR_DETECT */
        recovState = I2C_CLRERR_STATE;
    }
    else if (adap->status != I2C_INIT_STATE)
    {
#if (I2C_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)I2C_MODULE_ID, (uint8)I2C_INSTANCE_ID, (uint8)I2C_RECOVER_ID,
                              (uint8)I2C_E_UNINIT);
#endif /* I2C_DEV_ERROR_DETECT */
        recovState = I2C_CLRERR_STATE;
    }
    else
    {
        /* check and update adap owner statue */
        SchM_Enter_I2c_I2C_EXCLUSIVE_AREA_00();
        if (adap->adap_State == I2C_ADAP_IDLE)
        {
            adap->adap_State = I2C_ADAP_BUSY;
            busyFlag = TRUE;
        }
        SchM_Exit_I2c_I2C_EXCLUSIVE_AREA_00();

        if (TRUE == busyFlag)
        {
            ret = sdrv_I2c_recover(adap);

            /* update adap owner statue */
            SchM_Enter_I2c_I2C_EXCLUSIVE_AREA_00();
            adap->adap_State = I2C_ADAP_IDLE;
            SchM_Exit_I2c_I2C_EXCLUSIVE_AREA_00();

            if (ret != 0)
            {
                recovState = I2C_CLRERR_STATE;
            }
            else
            {
                recovState = I2C_CLRPASS_STATE;
            }
        }
        else
        {
            recovState = I2C_CLRERR_STATE;
        }
    }

    return recovState;
}

#define I2C_STOP_SEC_CODE
#include "I2c_MemMap.h"

#define I2C_START_SEC_CODE_FAST
#include "I2c_MemMap.h"
/**
 * @brief Main function handler for all I2C channels.
 *
 * This function iterates over all I2C channels and calls the
 * I2c_MainFunctionHandling function for each channel. This allows
 * the I2C driver to perform periodic tasks, such as processing
 * transactions, handling timeouts, or managing state transitions
 * for each channel individually.
 *
 * The function is designed to be called periodically by the scheduler
 * to ensure that all I2C channels are serviced in a timely manner.
 */
void I2c_MainfunctionHandling(void)
{
    /* PRQA S 2877 2 */
    for (uint8 I2cId = 0U; I2cId < I2C_CHN_NUM; I2cId++)
    {
        I2c_MainFunctionHandling(I2cId);
    }
}

#define I2C_STOP_SEC_CODE_FAST
#include "I2c_MemMap.h"
